home *** CD-ROM | disk | FTP | other *** search
- ////////////////////////////////////////////////////////////
- // UNWIND.CPP
- // Copyright 1994 Gregory Colvin.
- // May be distributed free with this notice.
-
- #include "unwind.h"
-
- static Unwindable* Newbie; // stack of newbies
- static Handler Top; // default handler
- Handler* Handler::handler=&Top; // current handler
- unsigned Unwindable::count; // count of objects
-
- // Set size and push on stack of newbies.
- void* Unwindable::operator new(size_t size) {
- Unwindable* p = (Unwindable*)::operator new(size);
- p->size = size;
- p->link = Newbie, Newbie = p;
- return p;
- }
-
- // True iff *this is a subobject of *w.
- inline int Unwindable::within(Unwindable* w) {
- return (char*)w <= (char*)this
- && (char*)w + w->size >= (char*)this + size;
- }
-
- // If p is under construction by new then if *p is complete
- // object pop it off stack of newbies, else pop subobjects
- // of *p off of and push p onto stack for current handler.
- void Handler::push(Unwindable* p,size_t sz) {
- p->size = sz;
- if (Newbie && p->within(Newbie)) {
- if (Newbie->size == p->size)
- Newbie = p->link;
- } else {
- for (Unwindable* stack= handler->link;
- stack && stack->within(p);
- stack = handler->link)
- handler->link = stack->link;
- p->link = handler->link, handler->link = p;
- }
- }
-
- // Pop and destroy all Unwindables on stack for current
- // handler and restore context of handler.
- void Handler::Throw(int err) {
- for (Unwindable* stack= handler->link;
- stack;
- stack = handler->link)
- handler->link = stack->link, stack->~Unwindable();
- if (handler != &Top)
- longjmp(handler->buf,err);
- abort();
- }
-
-
- #ifdef TEST
- #include <iostream.h>
-
- struct Test : Unwindable {
- int n;
- Unwindable sub;
- Unwindable* psub;
- Test(int i) : n(i) {
- UNWINDABLE;
- psub = new Unwindable();
- cout << "Test " << n << " " << this << endl;
- }
- virtual ~Test() {
- cout << "~Test " << n << " " << this << endl;
- n = 0;
- delete psub;
- }
- };
-
- int test(int n_try, int curr_try=0) {
- try {
- cout << "try in test " << curr_try << endl;
- Test local(curr_try);
- if (curr_try < n_try)
- return test(n_try,++curr_try);
- else {
- cout << "throw in test " << curr_try << endl;
- throw(-1);
- }
- } catch(int x) {
- cout << "catch " << x << " and rethrow in test "
- << curr_try << endl;
- throw(x);
- }
- return curr_try;
- }
-
- int main() {
- int n_test;
- cout << "enter number of test recursions: ";
- cin >> n_test;
- Test* pTest= new Test(-1);
- try {
- return test(n_test);
- } catch(int thrown) {
- cout << "catch " << thrown << " in main" << endl;
- }
- delete pTest;
- cout << "Count " << Unwindable::Count() << endl;
- return 0;
- }
- #endif
-
-